package com.xxdb.data;

import cn.snowsoft.iot.module.cps.dal.dataobject.equipment.EquipmentDO;
import com.alibaba.fastjson.JSONArray;
import com.xxdb.DBConnection;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


/**
 * @author chen_gang
 * @date 2023/11/16 16:24
 */
@Slf4j
@Component
public class DolphinDBUtils implements DisposableBean, ApplicationRunner {

    @Value("${dolphin.dbPath:}")
    private String dbPath;
    /**
     * 用户ID
     */
    @Value("${dolphin.userId:}")
    private String userId;
    /**
     * 密码
     */
    @Value("${dolphin.password:}")
    private String password;

    /**
     * hostName
     */
    @Value("${dolphin.hostName:}")
    private String hostName;

    /**
     * 数据节点1端口
     */
    @Value("${dolphin.port1:8921}")
    private int port1;


    /**
     * DolphinDB连接对象
     */
    private static DBConnection CONN;

    /**
     * 根据查询条件查询时序数据库历史数据
     *
     * @param tableName  表名
     * @param columnName 列名
     * @param begin      开始时间
     * @param end        结束时间
     * @return 查询结果
     */
    public BasicTable searchHistoryData(String tableName, String columnName, String begin, String end) {
        try {
            BasicTable table = (BasicTable) CONN.run(String.format("select thetime, %s from loadTable('%s','%s') where thetime >= %s and thetime <= %s",
                columnName, dbPath, "pt_" + tableName, begin, end));
            return table;
        } catch (IOException e) {
            log.error("历史数据查询失败");
            return null;
        }
    }

    public BasicTable searchHistoryStatistic(String tableName, String columnName, String begin, String end) {
        try {
            BasicTable table = (BasicTable) CONN.run(String.format("select last(%s) as lastValue,avg(%s) as avgValue,max(%s) as maxValue,min(%s) as minValue ,max(KG) - min(KG) as maxDiff from loadTable('%s','%s') where thetime >= %s and thetime <= %s",
                    columnName,columnName,columnName,columnName, dbPath, "pt_" + tableName, begin, end));
            return table;
        } catch (IOException e) {
            log.error("历史数据查询失败");
            return null;
        }
    }

    /**
     * 创建设备数据表
     *
     * @param equipment 设备
     * @param jsonArray  属性字段 [{"name": "属性编码", "type":16}]
     * @return Boolean
     */
    public Boolean createDeviceTable(EquipmentDO equipment, JSONArray jsonArray) {
        try {
            List<Entity> arguments = new ArrayList<>();
            arguments.add(new BasicString(dbPath));
            arguments.add(new BasicString(equipment.getEquipmentCode()));
            arguments.add(new BasicString(jsonArray.toJSONString()));
            CONN.run("IotCps::createDeviceTable", arguments);
        } catch (IOException e) {
            log.error("数据库创建失败: ", e);
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 删除设备数据表
     *
     * @param equipment 设备
     * @return Boolean
     */
    public Boolean deleteDeviceTable(EquipmentDO equipment) {
        try {
            List<Entity> arguments = new ArrayList<>();
            arguments.add(new BasicString(dbPath));
            arguments.add(new BasicString(equipment.getEquipmentCode()));
            CONN.run("IotCps::deleteDeviceTable", arguments);
        } catch (IOException e) {
            log.error("数据库删除失败: ", e);
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * @throws Exception 抛出异常
     */
    @Override
    public void destroy() throws Exception {
        if (CONN != null) {
            CONN.close();
        }
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        if (StringUtils.isBlank(dbPath)) {
            // 数据库
            log.error("未配置dolphin.dbPath");
            return;
        }
        if (StringUtils.isBlank(hostName)) {
            log.error("未配置dolphin.hostName");
            return;
        }
        // 连接数据节点
        CONN = new DBConnection();
        CONN.connect(hostName, port1, userId, password, "use IotCps", false, (String[])null, true);
    }
}
